home *** CD-ROM | disk | FTP | other *** search
- /* IP-related user commands
- * Copyright 1991 Phil Karn, KA9Q
- */
- /* Mods by PA0GRI */
- #include <stdio.h>
- #include "global.h"
- #include "config.h"
- #include "mbuf.h"
- #include "internet.h"
- #include "timer.h"
- #include "netuser.h"
- #include "iface.h"
- #include "session.h"
- #include "ip.h"
- #include "cmdparse.h"
- #include "commands.h"
- #include "rip.h"
- #include "rspf.h"
- #include "domain.h"
- #include "pktdrvr.h"
-
- int32 Ip_addr;
- int Route_Sort=1;
-
- static int doadd __ARGS((int argc,char *argv[],void *p));
- #ifdef IPACCESS
- static int doaccess __ARGS((int argc,char *argv[],void *p));
- #endif
- static int dodrop __ARGS((int argc,char *argv[],void *p));
- static int doflush __ARGS((int argc,char *argv[],void *p));
- static int doipaddr __ARGS((int argc,char *argv[],void *p));
- static int doipstat __ARGS((int argc,char *argv[],void *p));
- static int dolook __ARGS((int argc,char *argv[],void *p));
- static int dortimer __ARGS((int argc,char *argv[],void *p));
- static int dottl __ARGS((int argc,char *argv[],void *p));
- int doipheard __ARGS((int argc,char *argv[],void *p));
- static int doiphport __ARGS((int argc,char *argv[],void *p));
- static int doiphsize __ARGS((int argc,char *argv[],void *p));
- void dumproute __ARGS((struct route *rp,char *p));
- static int doroutesort __ARGS((int argc,char *argv[],void *p));
-
- static struct cmds DFAR Ipcmds[] = {
- #ifdef IPACCESS
- "access", doaccess, 0, 0, NULLCHAR,
- #endif
- "address", doipaddr, 0, 0, NULLCHAR,
- "heard", doipheard, 0, 0, NULLCHAR,
- "hport", doiphport, 0, 0, NULLCHAR,
- "hsize", doiphsize, 0, 0, NULLCHAR,
- "rtimer", dortimer, 0, 0, NULLCHAR,
- "status", doipstat, 0, 0, NULLCHAR,
- "ttl", dottl, 0, 0, NULLCHAR,
- NULLCHAR,
- };
- /* "route" subcommands */
- static struct cmds Rtcmds[] = {
- "add", doadd, 0, 3,
- "route add <dest addr>[/<bits>] <if name> [<gateway> | direct [metric]]",
-
- "addprivate", doadd, 0, 3,
- "route addprivate <dest addr>[/<bits>] <if name> [<gateway> | direct [metric]]",
-
- "drop", dodrop, 0, 2,
- "route drop <dest addr>[/<bits>]",
-
- "flush", doflush, 0, 0,
- NULLCHAR,
-
- "lookup", dolook, 0, 2,
- "route lookup <dest addr>",
-
- "sort", doroutesort, 0, 0,
- NULLCHAR,
-
- NULLCHAR,
- };
-
- int
- doip(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- return subcmd(Ipcmds,argc,argv,p);
- }
- #ifdef IPACCESS
- static int
- doaccess(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct iface *ifp;
- int32 source,target;
- unsigned sbits,tbits;
- char *bitp;
- int16 lport,hport,protocol,state;
- char *cp; /* for printing the table */
- struct rtaccess *tpacc;
- struct rtaccess *btacc;
- struct rtaccess *bfacc;
- struct rtaccess *head;
- char tmpbuf[15];
-
- if(argc == 1){ /* print out the table */
- tprintf("Source Address Len Dest Address Len Interface Proto Low High State\n");
- for(tpacc = IPaccess;tpacc != NULLACCESS;tpacc = tpacc->nxtiface){
- for(btacc = tpacc;btacc != NULLACCESS;btacc = btacc->nxtbits){
- if(btacc->source != 0)
- cp = inet_ntoa(btacc->source);
- else
- cp = "all";
- tprintf("%-16s",cp);
- tprintf("%2u ",btacc->sbits);
- if(btacc->target != 0)
- cp = inet_ntoa(btacc->target);
- else
- cp = "all";
- tprintf("%-16s",cp);
- tprintf("%2u ",btacc->bits);
- tprintf("%-13s",btacc->iface->name);
- switch (btacc->protocol) {
- case 0:
- cp = "any";
- break;
- case ICMP_PTCL:
- cp = "icmp";
- break;
- case TCP_PTCL:
- cp = "tcp";
- break;
- case UDP_PTCL:
- cp = "udp";
- break;
- default:
- cp = itoa(btacc->protocol,tmpbuf,10);
- }
- tprintf("%-5s ",cp);
- tprintf("%5u ",btacc->lowport);
- tprintf("%5u ",btacc->highport);
- if(btacc->status)
- cp = "deny";
- else
- cp = "permit";
- tprintf("%-6s\n",cp);
- }
- }
- return 0;
- }
-
- if(strcmp(argv[1],"permit") == 0){
- state = 0;
- } else {
- if((strcmp(argv[1],"deny") == 0)
- || (strcmp(argv[1],"delete") == 0)){
- state = -1;
- } else {
- tprintf(" Format: ip access <permit|deny|delete> <proto> <src addr>[/<bits>] <dest addr>[/<bits>] <if name> [low [high]]\n");
- return 1;
- }
- }
-
- switch (*argv[2]){
- case 'a': /* ANY */
- protocol = 0;
- break;
- case 'i': /* ICMP */
- protocol = ICMP_PTCL;
- break;
- case 't': /* TCP */
- protocol = TCP_PTCL;
- break;
- case 'u': /* UDP */
- protocol = UDP_PTCL;
- break;
- default:
- protocol = atoi(argv[2]);
- }
-
- if(strcmp(argv[3],"all") == 0){
- source = 0;
- sbits = 0;
- } else {
- /* If IP address is followed by an optional slash and
- * a length field, (e.g., 128.96/16) get it;
- * otherwise assume a full 32-bit address
- */
- if((bitp = strchr(argv[3],'/')) != NULLCHAR){
- /* Terminate address token for resolve() call */
- *bitp++ = '\0';
- sbits = atoi(bitp);
- } else
- sbits = 32;
-
- if((source = resolve(argv[3])) == 0){
- tprintf(Badhost,argv[3]);
- return 1;
- }
- }
- if(strcmp(argv[4],"all") == 0){
- target = 0;
- tbits = 0;
- } else {
- if((bitp = strchr(argv[4],'/')) != NULLCHAR){
- *bitp++ = '\0';
- tbits = atoi(bitp);
- } else
- tbits = 32;
-
- if((target = resolve(argv[4])) == 0){
- tprintf(Badhost,argv[4]);
- return 1;
- }
- }
-
- if((ifp = if_lookup(argv[5])) == NULLIF){
- tprintf(Badinterface,argv[5]);
- return 1;
- }
-
- if(((protocol != TCP_PTCL) && (protocol != UDP_PTCL)) || (argc < 7)) {
- lport = 0;
- hport = 0;
- } else {
- if(strcmp(argv[6],"all") == 0){
- lport = 0;
- } else {
- lport = atoi(argv[6]);
- }
- if((argc < 8) || (lport == 0))
- hport = lport;
- else
- hport = atoi(argv[7]);
- }
-
- if(strcmp(argv[1],"delete") == 0){
- head = IPaccess;
- for(tpacc = IPaccess;tpacc != NULLACCESS;head = tpacc,tpacc = tpacc->nxtiface){
- if(tpacc->iface == ifp){
- for(btacc = tpacc;btacc != NULLACCESS;
- head = btacc,btacc = btacc->nxtbits){
- if((btacc->protocol == protocol) &&
- (btacc->source == source) &&
- (btacc->sbits == sbits) &&
- (btacc->target == target) &&
- (btacc->bits == tbits) &&
- (btacc->lowport == lport) &&
- (btacc->highport == hport)) { /*match*/
- bfacc = btacc; /* save to unalloc */
- /*now delete. watch for special cases*/
- if(btacc != tpacc){ /* not at head of list */
- head->nxtbits = btacc->nxtbits;
- free(bfacc);
- return 0;
- }
- if(btacc == IPaccess){ /* real special case */
- if(IPaccess->nxtbits == NULLACCESS)
- IPaccess = btacc->nxtiface;
- else {
- IPaccess = btacc->nxtbits;
- (btacc->nxtbits)->nxtiface = btacc->nxtiface;
- }
- } else { /* we know tpacc=btacc <> IPaccess */
- if(btacc->nxtbits == NULLACCESS)
- head->nxtiface = btacc->nxtiface;
- else {
- head->nxtiface = btacc->nxtbits;
- (btacc->nxtbits)->nxtiface = btacc->nxtiface;
- }
- }
- free(bfacc);
- return 0;
- }
- }
- }
- }
- tprintf("Not found.\n");
- return 1;
- }
- /* add the access */
- addaccess(protocol,source,sbits,target,tbits,ifp,lport,hport,state);
- return 0;
- }
- #endif
- static int
- doipaddr(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- int32 n;
-
- if(argc < 2) {
- tprintf("%s\n",inet_ntoa(Ip_addr));
- } else if((n = resolve(argv[1])) == 0){
- tprintf(Badhost,argv[1]);
- return 1;
- } else
- Ip_addr = n;
- return 0;
- }
- static int
- dortimer(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- return setlong(&ipReasmTimeout,"IP reasm timeout (sec)",argc,argv);
- }
- static int
- dottl(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- return setlong(&ipDefaultTTL,"IP Time-to-live",argc,argv);
- }
-
-
- char RouteHeader[] = "Destination Len Interface Gateway Metric P Timer Use\n";
-
- /* Display and/or manipulate routing table */
- int
- doroute(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- register int i,j,k,l,m,bits,numflg,flow_tmp;
- register struct route *rp;
- char *temp,temp2[80];
-
- if(argc >= 2)
- return subcmd(Rtcmds,argc,argv,p);
-
- /* Dump IP routing table
- * Dest Len Interface Gateway Use
- * 192.001.002.003 32 sl0 192.002.003.004 0
- * modified for Sorted output - D. Crompton 2.92
- */
-
- flow_tmp=Current->flowmode;
- Current->flowmode=1;
-
- tputs(RouteHeader);
-
- for(j=0,bits=31;bits>=0;bits--)
- for(i=0;i<HASHMOD;i++)
- for(rp = Routes[bits][i];rp != NULLROUTE;j++,rp = rp->next);
-
- if (j){
-
- temp=mallocw(j*80);
-
- for(bits=31,k=0;bits>=0;bits--)
- for(i=0;i<HASHMOD;i++)
- for(rp = Routes[bits][i];rp != NULLROUTE;rp = rp->next,k+=80)
- dumproute(rp,&temp[k]);
-
- if (Route_Sort) qsort(temp,(size_t)j,80,strcmp);
-
- for (i=0,k=4;i<j;i++,k+=80) {
- tprintf("%s",&temp[k]);
- if (tprintf("\n") == EOF)
- {
- Current->flowmode=flow_tmp;
- free(temp);
- return 0;
- }
- }
- free(temp);
- }
- if(R_default.iface != NULLIF){
- dumproute(&R_default,temp2);
- tprintf("%s\n",temp2);
- }
- Current->flowmode = flow_tmp;
- return 0;
- }
-
- /* Dump a routing table entry */
- void
- dumproute(rp,temp)
- register struct route *rp;
- char *temp;
- {
- char *cp;
- unsigned int a=0;
- char *name;
-
- if(rp->target != 0) {
- if(DTranslate && (name = resolve_a(rp->target,!DVerbose)) != NULLCHAR) {
- a+=4;
- strcpy(temp,name);
- free(name);
- } else {
- cp = inet_ntobos(rp->target);
- a=sprintf(temp,"%4s",cp);
- }
- cp = inet_ntoa(rp->target);
- } else {
- cp = "default";
- }
- a+=sprintf(&temp[a],"%-16.16s ",cp);
- a+=sprintf(&temp[a],"%-4u",rp->bits);
- a+=sprintf(&temp[a],"%-9.9s ",rp->iface->name);
- if(rp->gateway != 0)
- cp = inet_ntoa(rp->gateway);
- else
- cp = "";
- a+=sprintf(&temp[a],"%-16.16s ",cp);
- a+=sprintf(&temp[a],"%-6lu ",rp->metric);
- a+=sprintf(&temp[a],"%c ",(rp->flags & RTPRIVATE) ? 'P' : ' ');
- if(rp->timer.state == TIMER_STOP){
- if(rp->timer.duration == 1) a+=sprintf(&temp[a],"rspf ");
- else a+=sprintf(&temp[a],"man ");
- } else {
- a+=sprintf(&temp[a],"%-7lu",read_timer(&rp->timer) / 1000L);
- }
- sprintf(&temp[a],"%lu",rp->uses);
- }
-
-
- /* Sort Route dump */
- static int
- doroutesort(argc,argv,p)
- int argc ;
- char *argv[] ;
- void *p;
- {
- extern int Route_Sort;
-
- return setbool(&Route_Sort,"Route Sort flag",argc,argv);
- }
-
-
- /* Add an entry to the routing table
- * E.g., "add 1.2.3.4 ax0 5.6.7.8 3"
- */
- static int
- doadd(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct iface *ifp;
- int32 dest,gateway;
- unsigned bits;
- char *bitp;
- int32 metric;
- char private;
-
- if(strncmp(argv[0],"addp",4) == 0)
- private = 1;
- else
- private = 0;
- if(strcmp(argv[1],"default") == 0){
- dest = 0L;
- bits = 0;
- } else {
- /* If IP address is followed by an optional slash and
- * a length field, (e.g., 128.96/16) get it;
- * otherwise assume a full 32-bit address
- */
- if((bitp = strchr(argv[1],'/')) != NULLCHAR){
- /* Terminate address token for resolve() call */
- *bitp++ = '\0';
- bits = atoi(bitp);
- } else
- bits = 32;
-
- if((dest = resolve(argv[1])) == 0){
- tprintf(Badhost,argv[1]);
- return 1;
- }
- }
- if((ifp = if_lookup(argv[2])) == NULLIF){
- tprintf(Badinterface,argv[2]);
- return 1;
- }
-
- metric = 1;
-
- if(argc > 3){
- /* Next "trick is needed to set the metric on subnets
- * higher as the default 1 for rspf.
- * route add subnet/bits iface default 10
- */
- if(strcmp(argv[3],"direct") == 0){ /* N1BEE */
- gateway = 0;
- /* calculate a nice metric based on subnet mask size */
- if(bits != 0 && bits < 32)
- metric = (39 - bits) * 5 / 17;
- } else {
- if((gateway = resolve(argv[3])) == 0){
- tprintf(Badhost,argv[3]);
- return 1;
- }
- }
- } else {
- gateway = 0;
- }
- if (argc > 4)
- metric = atol(argv[4]);
-
- if(rt_add(dest,bits,gateway,ifp,metric,0,private) == NULLROUTE)
- tprintf("Can't add route\n");
- #ifdef RSPF
- if(!private)
- rspfrouteupcall(dest,bits,gateway); /* Do an RSPF upcall */
- #endif /* RSPF */
- return 0;
- }
- /* Drop an entry from the routing table
- * E.g., "drop 128.96/16
- */
- static int
- dodrop(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- char *bitp;
- unsigned bits;
- int32 n;
-
- if(strcmp(argv[1],"default") == 0){
- n = 0L;
- bits = 0;
- } else {
- /* If IP address is followed by an optional slash and length field,
- * (e.g., 128.96/16) get it; otherwise assume a full 32-bit address
- */
- if((bitp = strchr(argv[1],'/')) != NULLCHAR){
- /* Terminate address token for resolve() call */
- *bitp++ = '\0';
- bits = atoi(bitp);
- } else
- bits = 32;
-
- if((n = resolve(argv[1])) == 0){
- tprintf(Badhost,argv[1]);
- return 1;
- }
- }
- return rt_drop(n,bits);
- }
- /* Force a timeout on all temporary routes */
- static int
- doflush(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- register struct route *rp;
- struct route *rptmp;
- int i,j;
-
- if(R_default.timer.state == TIMER_RUN){
- rt_drop(0,0); /* Drop default route */
- }
- for(i=0;i<HASHMOD;i++){
- for(j=0;j<32;j++){
- for(rp = Routes[j][i];rp != NULLROUTE;rp = rptmp){
- rptmp = rp->next;
- if(rp->timer.state == TIMER_RUN){
- rt_drop(rp->target,rp->bits);
- }
- }
- }
- }
- return 0;
- }
-
- static int
- dolook(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct route *rp;
- int32 addr;
- char temp[80];
-
- addr = resolve(argv[1]);
- if(addr == 0){
- tprintf(Badhost,argv[1]);
- return 1;
- }
- if((rp = rt_lookup(addr)) == NULLROUTE){
- tprintf("Host %s (%s) unreachable\n",argv[1],inet_ntoa(addr));
- return 1;
- }
-
- dumproute(rp,temp);
- tputs(RouteHeader);
- tprintf("%s\n",&temp[4]);
-
- return 0;
- }
-
- static int
- doipstat(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- register struct reasm *rp;
- register struct frag *fp;
- int i;
-
- for(i=1;i<=NUMIPMIB;i++){
- tprintf("(%2u)%-20s%10lu",i,
- Ip_mib[i].name,Ip_mib[i].value.integer);
- if(i % 2)
- tprintf(" ");
- else
- tprintf("\n");
- }
- if((i % 2) == 0)
- tprintf("\n");
-
- if(Reasmq != NULLREASM)
- tprintf("Reassembly fragments:\n");
- for(rp = Reasmq;rp != NULLREASM;rp = rp->next){
- tprintf("src %s",inet_ntoa(rp->source));
- tprintf(" dest %s",inet_ntoa(rp->dest));
- if(tprintf(" id %u pctl %u time %lu len %u\n",
- rp->id,uchar(rp->protocol),read_timer(&rp->timer),
- rp->length) == EOF)
- break;
- for(fp = rp->fraglist;fp != NULLFRAG;fp = fp->next){
- if(tprintf(" offset %u last %u\n",fp->offset,
- fp->last) == EOF)
- break;
- }
- }
- return 0;
- }
-
- /* IP heard logging - WG7J */
- static struct iph *iph_create __ARGS((int32 addr));
- static struct iph *iph_lookup __ARGS((int32 addr));
- struct iph *Iph;
-
- static int Maxipheard = MAXIPHEARD;
-
- static int doiphsize(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- return setint(&Maxipheard,"Max ip-heard",argc,argv);
- }
-
- /* Configure a port to do ip-heard logging */
- static int
- doiphport(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- return(dosetflag(argc,argv,p,LOG_IPHEARD, 0));
- }
-
- int
- doipheard(argc, argv, p)
- int argc;
- char *argv[];
- void *p;
- {
- struct iph *iph;
-
- if(tputs("Tcp/Ip systems heard:\nAddress Port Since Pkts\n") == EOF)
- return EOF;
- for(iph=Iph;iph;iph=iph->next) {
- if(tprintf("%-22s %-8s %12s %5d\n",inet_ntoa(iph->addr),iph->iface->name,
- tformat(secclock() - iph->time),iph->count) == EOF)
- return EOF;
- }
- return 0;
- }
-
- void
- log_ipheard(addr,ifp)
- int32 addr;
- struct iface *ifp;
- {
- struct iph *niph;
-
- if((niph = iph_lookup(addr)) == NULLIPH)
- if((niph = iph_create(addr)) == NULLIPH)
- return;
- niph->iface = ifp;
- niph->count++;
- niph->time = secclock();
- }
-
- /* Look up an entry in the ip data base */
- struct iph *
- iph_lookup(addr)
- int32 addr;
- {
- register struct iph *ip;
- struct iph *last = NULLIPH;
-
- for(ip = Iph;ip != NULLIPH;last = ip,ip = ip->next){
- if(ip->addr == addr) {
- if(last != NULLIPH){
- /* Move entry to top of list */
- last->next = ip->next;
- ip->next = Iph;
- Iph = ip;
- }
- return ip;
- }
- }
- return NULLIPH;
- }
-
- /* Create a new entry in the source database */
- /* If there are too many entries, override the oldest one - WG7J */
- static struct iph *
- iph_create(addr)
- int32 addr;
- {
- static int numdb;
- register struct iph *iph;
- struct iph *last = NULLIPH;
-
- if(Maxipheard && numdb == Maxipheard) {
- /* find and use last one in list */
- for(iph = Iph;iph->next != NULLIPH;last = iph,iph = iph->next);
- /* delete entry from end */
- last->next = NULLIPH;
- } else { /* create a new entry */
- numdb++;
- iph = (struct iph *)callocw(1,sizeof(struct iph));
- }
- iph->addr = addr;
- iph->next = Iph;
- Iph = iph;
-
- return iph;
- }
-